using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Web;
using Microsoft.ReportingServices.Interfaces;
using AUSRIS.Framework.Logging;
using AUSRIS.Reports.Extensions.Security.Authorization;

namespace AUSRIS.Reports.Extensions.Security.Authentication
{
	public class AuthenticationExtension : IAuthenticationExtension
	{
		#region Private Fields

		private ISecurityProvider securityProvider;

		#endregion

		#region Constructor(s)

		public AuthenticationExtension()
		{
			this.securityProvider = ProviderFactory.GetProvider<ISecurityProvider>();
		}

		#endregion

		#region IAuthenticationExtension Members

		/// <summary>
		/// Required by IAuthenticationExtension. The report server calls the 
		/// GetUserInfo methodfor each request to retrieve the current user 
		/// identity.
		/// </summary>
		/// <param name="userIdentity">
		/// Represents the identity of the current user. 
		/// The value of IIdentity may appear in a user interface and 
		/// should be human readable
		/// </param>
		/// <param name="userId">represents a pointer to a unique user identity
		/// </param>
		public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)
		{
#if DEBUG
			Log.Debug(Log.GetSource(), "Getting User Info");
#endif
			try
			{
				//If the current user identity is not null, set the userIdentity parameter to the current user
				if ( HttpContext.Current != null && HttpContext.Current.User != null )
				{
					userIdentity = HttpContext.Current.User.Identity;
				}
				else
				{
					userIdentity = new GenericIdentity(string.Empty);
				}
			}
			catch ( Exception ex )
			{
				userIdentity = new GenericIdentity(string.Empty);
#if DEBUG
				Log.Fatal(Log.GetSource(), ex.ToString());
#endif
			}

			//Initialize a pointer to the current user id to zero
			userId = IntPtr.Zero;
		}

		/// <summary>
		/// The IsValidPrincipalName method is called by the report server when 
		/// the report server sets security on an item. This method validates 
		/// that the user name is valid for Windows.The principal name needs to 
		/// be a user, group, or builtin account name.
		/// </summary>
		/// <param name="principalName">
		/// A user, group, or built-in account name
		/// </param>
		/// <returns>true when the principle name is valid</returns>
		public bool IsValidPrincipalName(string principalName)
		{
#if DEBUG
			Log.Debug(Log.GetSource(), "principalName: {0}", principalName);
#endif
			return this.securityProvider.IsValidPrincipalName(principalName);
		}

		/// <summary>
		/// Indicates whether a supplied username and password are valid.
		/// </summary>
		/// <param name="userName">The supplied username</param>
		/// <param name="password">The supplied password</param>
		/// <param name="authority">
		/// Optional. The specific authority to use to
		/// authenticate a user. For example, in Windows it would be a Windows 
		/// Domain
		/// </param>
		/// <returns>true when the username and password are valid</returns>
		public bool LogonUser(string userName, string password, string authority)
		{
#if DEBUG
			Log.Debug(Log.GetSource(), "userName: {0}, password: {1}, authority: {2}", userName, password ?? "", authority);
#endif
			return this.securityProvider.IsValidCredentials(userName, password, authority);
		}

		#endregion

		#region IExtension Members

		/// <summary>
		/// Required by IExtension
		/// </summary>
		public string LocalizedName
		{
			get
			{
				return null;
			}
		}

		/// <summary>
		/// Required by IExtension
		/// </summary>
		/// <param name="configuration">
		/// Configuration data as an XML string that is stored along with the Extension element in
		/// the configuration file.
		/// </param>
		public void SetConfiguration(string configuration)
		{
			//TODO: read any required config information from xml
		}

		#endregion
	}
}
